import service
import uthread
import trinity
import blue
import geo2
import base
boxSizes = [15,
 60,
 240,
 960,
 3840,
 15360,
 61440,
 245760]

class PosAnchorSvc(service.Service):
    __guid__ = 'svc.posAnchor'
    __exportedcalls__ = {}
    __notifyevents__ = ['DoBallRemove', 'ProcessSessionChange']
    __dependencies__ = ['michelle']

    def __init__(self):
        service.Service.__init__(self)
        self.updateTimer = None
        self.cube = None
        self.cursor = None
        self.selection = None
        self.cursorSize = 2500.0
        self.active = 0
        self.posID = None



    def Run(self, memStream = None):
        service.Service.Run(self, memStream)



    def Stop(self, stream):
        self.KillTimer()
        self.HideCursor()
        service.Service.Stop(self)



    def ProcessSessionChange(self, isremote, session, change):
        self.KillTimer()
        self.HideCursor()



    def StartMovingCursor(self):
        if not self.cursor:
            return 
        bp = sm.GetService('michelle').GetBallpark()
        ego = bp.GetBall(bp.ego)



    def StopMovingCursor(self):
        print 'StopMovingCursor'



    def RefreshSelection(self):
        uthread.new(self.RefreshSelection_thread).context = 'svc.posAnchor.RefreshSelection'



    def RefreshSelection_thread(self):
        if (self.cursor is None):
            self.ShowCursor()
        scene = sm.GetService('sceneManager').GetRegisteredScene('default')
        del scene.children[:]
        cubeModel = blue.os.LoadObject('res:/Model/UI/lineCube.blue')
        bp = sm.GetService('michelle').GetBallpark()
        if (bp is None):
            return 
        balls = []
        for ballID in self.selection:
            ball = bp.GetBall(ballID)
            model = cubeModel.CloneTo()
            model.translationCurve = ball
            model.scaling.SetXYZ(ball.radius, ball.radius, ball.radius)
            model.scaling.Scale(0.5)
            scene.children.append(model)
            balls.append(ball)

        if len(balls):
            vecSeq = trinity.TriVectorSequencer()
            vecSeq.operator = trinity.TRIOP_ADD
            for ball in balls:
                vecSeq.functions.append(ball)

            vecSeqD = trinity.TriVectorSequencer()
            vecSeqD.operator = trinity.TRIOP_MULTIPLY
            vecF = trinity.TriVectorCurve()
            vecF.value.SetXYZ((1.0 / len(balls)), (1.0 / len(balls)), (1.0 / len(balls)))
            vecSeqD.functions.append(vecSeq)
            vecSeqD.functions.append(vecF)
            self.cursor.translationCurve = vecSeqD
            self.cursor.useCurves = 1
        else:
            self.cursor.translationCurve = None
            self.HideCursor()



    def GetType(self, ballID):
        bp = sm.GetService('michelle').GetBallpark()
        if (bp is None):
            return 
        slimItem = bp.GetInvItem(ballID)
        if (slimItem is None):
            return 
        typeID = slimItem.typeID
        groupID = cfg.invtypes.Get(typeID).groupID



    def DoBallRemove(self, ball, slimItem, terminal):
        if (ball is None):
            return 
        self.LogInfo('DoBallRemove::posAnchorSvc', ball.id)
        if (slimItem is None):
            return 
        if ((slimItem.itemID is None) or (slimItem.itemID < 0)):
            return 
        if (slimItem.itemID == self.posID):
            self.CancelAchorPosSelect()



    def ShowCursor(self):
        scene = sm.GetService('sceneManager').GetRegisteredScene2('default')
        if (scene is None):
            return 
        self.cursor = trinity.Load('res:/Model/UI/posCursor.red')
        self.cube = trinity.Load('res:/Model/UI/posGlassCube.red')
        s = float(boxSizes[(7 - self.boxSize)])
        blue.pyos.synchro.Sleep(1)
        self.yCursor = [self.cursor.children[0], self.cursor.children[1]]
        self.xCursor = [self.cursor.children[4], self.cursor.children[5]]
        self.zCursor = [self.cursor.children[2], self.cursor.children[3]]
        self.cube.scaling = (s,
         s,
         s)
        newScale = ((s * 0.075) * 0.25)
        self.cursor.scaling = (newScale,
         newScale,
         newScale)
        bp = sm.GetService('michelle').GetBallpark()
        ball = bp.GetBall(self.posID)
        pos = ball.GetVectorAt(blue.os.GetTime())
        self.cursor.translation = (pos.x,
         pos.y,
         pos.z)
        scene.objects.append(self.cursor)
        scene.objects.append(self.cube)
        self.Update()
        self.active = 1



    def RefreshCursorSize(self):
        if self.cursor:
            self.cursor.scaling.SetXYZ(self.cursorSize, self.cursorSize, self.cursorSize)



    def ScaleCursorUp(self):
        self.cursorSize = (self.cursorSize * 1.1)
        self.RefreshCursorSize()



    def ScaleCursorDown(self):
        self.cursorSize = max((self.cursorSize / 1.1), 5.0)
        self.RefreshCursorSize()



    def IsActive(self):
        return self.active



    def HideCursor(self):
        self.active = 0
        if not sm.IsServiceRunning('gameui'):
            return 
        scene2 = sm.StartService('sceneManager').GetRegisteredScene2('default')
        if (self.cursor and (self.cursor in scene2.objects)):
            scene2.objects.remove(self.cursor)
        if (self.cube and (self.cube in scene2.objects)):
            scene2.objects.remove(self.cube)
        self.cursor = None
        self.cube = None



    def MoveCursor(self, tf, dx, dy, camera):
        dev = eve.triapp.tridev
        X = (float(dx) / float(dev.width))
        Y = ((float(dy) / float(dev.height)) * -1)
        viewVec = camera.viewVec
        upVec = camera.upVec
        upVec.Scale(Y)
        rightVec = camera.rightVec
        rightVec.Scale(X)
        pos = (rightVec + upVec)
        cameraDistance = (geo2.Vec3Length(((camera.pos.x - self.cursor.translation[0]),
         (camera.pos.y - self.cursor.translation[1]),
         (camera.pos.z - self.cursor.translation[2]))) * 3.0)
        pos.Scale(cameraDistance)
        if (tf in self.yCursor):
            pos.x = 0.0
            pos.z = 0.0
        elif (tf in self.xCursor):
            pos.y = 0.0
            pos.z = 0.0
        elif (tf in self.zCursor):
            pos.x = 0.0
            pos.y = 0.0
        self.cursor.translation = ((self.cursor.translation[0] + pos.x),
         (self.cursor.translation[1] + pos.y),
         (self.cursor.translation[2] + pos.z))



    def GetBoxSize(self, radius):
        b = 0
        while ((radius > boxSizes[b]) and (b < 7)):
            b += 1

        return (7 - b)



    def StartAnchorPosSelect(self, posID):
        if self.IsActive():
            if (posID == self.posID):
                return 
            self.CancelAchorPosSelect()
        bp = sm.GetService('michelle').GetBallpark()
        slimItem = bp.GetInvItem(posID)
        if (slimItem is None):
            return 
        self.posID = posID
        typeID = slimItem.typeID
        self.boxSize = self.GetBoxSize(cfg.invtypes.Get(typeID).radius)
        import uix
        item = sm.StartService('michelle').GetItem(posID)
        if (item.groupID == const.groupControlTower):
            if (eve.Message('ConfirmStructureAnchor', {'item': (TYPEID, item.typeID)}, uix.YESNO, suppress=uix.ID_YES) != uix.ID_YES):
                return 
            self.SubmitAnchorPosSelect()
        else:
            self.ShowCursor()
            self.StartTimer()



    def CancelAchorPosSelect(self):
        self.KillTimer()
        self.HideCursor()
        self.posID = None



    def SubmitAnchorPosSelect(self):
        typeID = sm.GetService('michelle').GetItem(self.posID).typeID
        anchoringDelay = sm.GetService('godma').GetType(typeID).anchoringDelay
        eve.Message('AnchoringObject', {'delay': (anchoringDelay / 1000.0)})
        bp = sm.GetService('michelle').GetBallpark()
        ship = bp.GetBall(eve.session.shipid)
        x = y = z = 0
        if (sm.StartService('michelle').GetItem(self.posID).groupID != const.groupControlTower):
            (x, y, z,) = ((self.cube.translation[0] + ship.x), (self.cube.translation[1] + ship.y), (self.cube.translation[2] + ship.z))
        sm.GetService('pwn').Anchor(self.posID, (x,
         y,
         z))
        self.CancelAchorPosSelect()



    def CheckIsLegal(self, x, y, z, boxSize):
        print 'CheckIsLegal'



    def StartTimer(self):
        if self.updateTimer:
            return 
        self.timerCount = 0
        self.updateTimer = base.AutoTimer(25, self.Update)



    def KillTimer(self):
        self.updateTimer = None



    def Update(self):
        bp = sm.GetService('michelle').GetBallpark()
        ship = bp.GetBall(eve.session.shipid)
        x = (ship.x + self.cursor.translation[0])
        y = (ship.y + self.cursor.translation[1])
        z = (ship.z + self.cursor.translation[2])
        (boxx, boxy, boxz,) = bp.GetBoxCenter(self.boxSize, x, y, z)
        self.cube.translation = ((boxx - ship.x),
         (boxy - ship.y),
         (boxz - ship.z))




